using UnityEngine;
using System.Collections;
using Photon.Pun;
using MyNetwork;

// 网络化的玩家控制器 挂载在 solider2 上
public class SoliderController : MonoBehaviourPunCallbacks, IPunObservable
{
    private Animator anim;
    private CharacterController characterController;
    private Vector3 dir = Vector3.zero;

    // 发射口
    public Transform gunPos;
    // 是否处于发射状态 默认只有本地玩家的客户端显示了发射 需要手动同步状态给其他玩家
    // photontransformview photonanimatorview 完成了内部的同步
    // IPunObservable 观察者接口 用于手动同步变量
    private bool isShooting;
    private float _shootColdTime;
    public float BulletFlySpeed;
    // 一个弹匣 20 发子弹
    private sbyte _magazine = 20;
    // 初始 3 个弹匣
    private sbyte _totalMagazine = 3;
    // 能装填弹夹
    private bool _canMagazine = true;

    public int health = 30;

    public CameraWork cameraWork;

    public GameObject playerUIPrefab;

    private void Awake()
    {
        anim = GetComponent<Animator>();
        characterController = GetComponent<CharacterController>();
        if (!anim)
        {
            Debug.LogError("missing animator");
        }
    }
    private void Start()
    {
        if (photonView.IsMine)
        {
            cameraWork.OnStartFollowing();
        }
        if (playerUIPrefab != null)
        {
            GameObject uiPre = Instantiate(playerUIPrefab);
            // 通过内置消息机制调用方法 与直接调用方法效果相同? 报错
            // uiPre.SendMessage("SetTarget", this, SendMessageOptions.RequireReceiver);
            uiPre.GetComponent<PlayerUI>().SetTarget(this);
        }
        UnityEngine.SceneManagement.SceneManager.sceneLoaded += OnSceneLoaded;
    }
    private void Update()
    {
        if (!anim || !photonView.IsMine)
        {
            return;
        }
        // 血量为 0 时退回菜单场景的选择房间界面
        if (health <= 0)
        {
            FindObjectOfType<Launcher>().LeaveRoom();
        }
        float h = Input.GetAxisRaw("Horizontal");
        float v = Input.GetAxisRaw("Vertical");
        if (h != 0 || v != 0)
        {
            anim.SetBool("running", true);
            dir.x = h * 0.2f;
            dir.z = v * 0.2f;
            characterController.Move(dir);
        }
        else
        {
            anim.SetBool("running", false);
        }

        // 射击冷却时间
        if (_shootColdTime > 0)
        {
            _shootColdTime -= Time.deltaTime;
        }

        AnimatorStateInfo stateInfo = anim.GetCurrentAnimatorStateInfo(0);
        // 左键发射子弹
        if (!stateInfo.IsName("Base Layer.shoot") && Input.GetButtonDown("Fire1") && _magazine > 0 && _shootColdTime <= 0)
        {
            isShooting = true;
            anim.SetTrigger("shoot");
        }
        // 右键重新填装弹药
        if (Input.GetMouseButtonDown(1) && _totalMagazine > 0)
        {
            // 使用协程装弹药，延时 0.5 秒装好
            StartCoroutine(MagazineCor());
        }
    }
    public override void OnDisable()
    {
        base.OnDisable();
        UnityEngine.SceneManagement.SceneManager.sceneLoaded -= OnSceneLoaded;
    }
    // 装弹
    IEnumerator MagazineCor()
    {
        if (_canMagazine)
        {
            _canMagazine = false;
            yield return new WaitForSeconds(0.4f);
            _totalMagazine -= 1;
            _magazine = 20;
            _canMagazine = true;
        }
    }
    public void Shoot()
    {
        // 消耗 1 子弹
        _magazine -= 1;
        // 默认射速 1 秒 1 发子弹
        _shootColdTime = 1;
        // 从对象池取出一个子弹
        GameObject b = BulletPool.Instance.GetBullet();

        // 法1 直接设置世界坐标    + GunPos[0].up 确保子弹在枪管尾部一定距离时飞出，而不是与枪管发生碰撞
        b.transform.SetPositionAndRotation(gunPos.position, Quaternion.Euler(new Vector3(90, 0, -transform.eulerAngles.y)));

        // 给子弹初速度
        b.GetComponent<Bullet>().Rb.velocity = b.transform.TransformVector(Vector3.up) * BulletFlySpeed;

        isShooting = false;
    }
    // 如果要观察，将当前脚本拖拽到 photonview 列表中
    public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        // 对于当前玩家，可写时，将射击状态发送出去
        if (stream.IsWriting)
        {
            stream.SendNext(isShooting);
            stream.SendNext(health);
        }
        // 对于其他玩家，接收数据并保存
        else
        {
            this.isShooting = (bool)stream.ReceiveNext();
            this.health = (int)stream.ReceiveNext();
        }
    }
    void OnSceneLoaded(UnityEngine.SceneManagement.Scene scene, UnityEngine.SceneManagement.LoadSceneMode mode)
    {
        this.CallOnSceneLoaded(scene.buildIndex);
    }
    void CallOnSceneLoaded(int level)
    {
        // 玩家离开 切换场景 地图将要缩小 剩余玩家如果处在大地图的边界 重新回到小地图中心区域内
        // https://doc.photonengine.com/zh-cn/pun/current/demos-and-tutorials/pun-basics-tutorial/player-instantiation
    }

}
